class IUP_CANVAS
-- Creates an interface element that is a canvas - a working area for your 
-- application.
--
--  Note that some keys might remove the focus from the canvas. To avoid this, 
--  return IGNORE in the K_ANY callback.
-- 
-- The mouse cursor position can be programmatically controlled using the 
-- global attribute CURSORPOS.
-- 
-- When the canvas is displayed for the first time, the callback call order is 
-- always:	
-- 
-- MAP_CB()
-- RESIZE_CB()
-- ACTION()
-- 
-- When the canvas is resized the ACTION callback is always called after the 
-- RESIZE_CB callback.
-- Using with the CD library
-- 
-- When using the CD library to draw in a IupCanvas, you can use the callbacks 
-- to manage the canvas. The simplest way is to do:
-- 
-- MAP_CB   - calls cdCreateCanvas  (current size is not available yet)
-- UNMAP_CB - calls cdKillCanvas
-- RESIZE_CB - Calling cdCanvasActivate and cdCanvasGetSize returns the same 
--             values as given by the callback parameters.
--             Recalculate the drawing size, update the scrollbars if any.
-- ACTION - calls cdCanvasActivate 
--          then use CD primitives to draw the scene, 
--          finally calls cdCanvasFlush if using double buffer
-- SCROLL_CB - when using scrollbars, 
--             if this callback is defined the canvas must be manually redrawn,
--             call yourself the action callback or call IupUpdate.
--             In other words, if this callback is not defined 
--             the canvas is automatically redrawn.

inherit
	IUP_CONTAINER
		undefine
			execute_dragbegin,
			execute_dragdatasize,
			execute_dragdata,
			execute_dragend,
			execute_dropdata,
			execute_dropmotion
		redefine
			execute_map,
			execute_unmap,
			execute_destroy,
			execute_getfocus,
			execute_killfocus,
			execute_enterwindow,
			execute_leavewindow,
			execute_k_any,
			execute_help,
			execute_action_fnff,
			execute_focus,
			execute_motion,
			execute_keypress,
			execute_scroll,
			execute_wheel,
			execute_dropfiles,
			execute_resize,
			execute_button
		end
	IUP_WIDGET_BGCOLOR
	IUP_WIDGET_ACTIVE
	IUP_WIDGET_FONT
	IUP_WIDGET_EXPAND
	IUP_WIDGET_SCREENPOSITION
	IUP_WIDGET_POSITION
	IUP_WIDGET_MAXMIN_SIZE
	IUP_WIDGET_TIP
	IUP_WIDGET_SIZE
	IUP_WIDGET_RASTERSIZE
	IUP_WIDGET_USERSIZE
	IUP_WIDGET_ZORDER
	IUP_WIDGET_VISIBLE
	IUP_WIDGET_CHILD
	IUP_WIDGET_NAME
	IUP_WIDGET_FOCUS
	IUP_WIDGET_PROPAGATEFOCUS
	IUP_DRAG_AND_DROP
	IUP_WIDGET_CUSTOM_ATTRIBUTES


create {ANY}
	canvas

feature {ANY}

	canvas
		-- Create a canvas.
		local
			a_canvas, p: detachable POINTER
		do
			a_canvas := int_create_canvas(p)
			set_widget(a_canvas)
		end

	-- Special attributes for CD

	get_cd_canvas: CD_IUP
		do
			Result := internal_canvas
		end

	get_front_cd_canvas: CD_IUP
		do
			Result := front_canvas
		end

	-- Attributes

	set_backing_store (state: BOOLEAN)
		-- [Motif Only]: Controls the canvas backing store flag. The default 
		-- value is "True".
		do
			iup_open.set_attribute(Current, "BACKINGSTORE", boolean_to_yesno(state))
		end

	set_border (state: BOOLEAN)
		-- (creation only): Shows a border around the canvas. Default: "True".
		do
			iup_open.set_attribute(Current, "BORDER", boolean_to_yesno(state))
		end

	set_can_focus (state: BOOLEAN)
		-- (creation only) (non inheritable): enables the focus traversal of the 
		-- control. In Windows the canvas will respect CANFOCUS differently to 
		-- some other controls. Default: True.
		do
			iup_open.set_attribute(Current, "CANFOCUS", boolean_to_yesno(state))
		end

	-- Skip CAIRO_CR

	set_clip_rect (x1, y1, x2, y2: INTEGER)
		-- [Windows and GTK Only] (only during ACTION): Specifies a rectangle 
		-- that has its region invalidated for painting, it could be used for 
		-- clipping.	
		local
			str: STRING
		do
			str := x1.out
			str.append_string(" ")
			str.append_string(y1.out)
			str.append_string(" ")
			str.append_string(x2.out)
			str.append_string(" ")
			str.append_string(y2.out)

			iup_open.set_attribute(Current, "CLIPRECT", str)
		end

	set_cursor (name: STRING)
		-- Defines the element's cursor. See documentation. Default: ARROW
		do
			iup_open.set_attribute(Current, "CURSOR", name)
		end

	set_as_drop_files_target (state: BOOLEAN)
		-- [Windows and GTK Only] (non inheritable): Enable or disable the drop 
		-- of files. Default: False, but if DROPFILES_CB is defined when the 
		-- element is mapped then it will be automatically enabled.
		do
			iup_open.set_attribute(Current, "DROPFILESTARGET", boolean_to_yesno(state))
		end

	get_draw_size: TUPLE[INTEGER, INTEGER]
		-- (non inheritable): The size of the drawing area in pixels. This size is
		-- also used in the RESIZE_CB callback.
		-- Notice that the drawing area size is not the same as RASTERSIZE. The 
		-- SCROLLBAR and BORDER attributes affect the size of the drawing area.
		local
			size: STRING
		do
			size := iup_open.get_attribute(Current, "DRAWSIZE")
			Result := components_of_size(size)
		end

	set_scroll_bar (state: BOOLEAN)
		-- (creation only): Associates a horizontal and/or vertical scrollbar to 
		-- the canvas. Default: "False". The secondary attributes are all non 
		-- inheritable.	
		do
			iup_open.set_attribute(Current, "SCROLLBAR", boolean_to_yesno(state))
		end

	-- Skip HDC_WMPAINT, HWND

	set_dx (dx: REAL)
		-- Size of the thumb in the horizontal scrollbar. Also the horizontal 
		-- page size. Default: "0.1".
		require
			dx >= 0
		do
			iup_open.set_attribute(Current, "DX", dx.out)
		end

	set_dy (dy: REAL)
		-- Size of the thumb in the vertical scrollbar. Also the vertical page 
		-- size. Default: "0.1".
		require
			dy >= 0
		do
			iup_open.set_attribute(Current, "DY", dy.out)
		end

	set_pos_x (pos: REAL)
		-- Position of the thumb in the horizontal scrollbar. Default: "0.0".
		require
			pos >= 0
		do
			iup_open.set_attribute(Current, "POSX", pos.out)
		end

	set_pos_y (pos: REAL)
		-- Position of the thumb in the vertical scrollbar. Default: "0.0".
		require
			pos >= 0
		do
			iup_open.set_attribute(Current, "POSY", pos.out)
		end

	set_x_min (value: REAL)
		-- Minimum value of the horizontal scrollbar. Default: "0.0".
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "XMIN", value.out)
		end

	set_x_max (value: REAL)
		-- Maximum value of the horizontal scrollbar. Default: "1.0".
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "XMAX", value.out)
		end

	set_y_min (value: REAL)
		-- Minimum value of the vertical scrollbar. Default: "0.0".
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "YMIN", value.out)
		end

	set_y_max (value: REAL)
		-- Maximum value of the vertical scrollbar. Default: "1.0".
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "YMAX", value.out)
		end

	set_line_x (value: REAL)
		-- The amount the thumb moves when an horizontal step is performed. 
		-- Default: 1/10th of DX. 
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "LINEX", value.out)
		end

	set_line_y (value: REAL)
		-- The amount the thumb moves when a vertical step is performed. 
		-- Default: 1/10th of DY.
		require
			value >= 0
		do
			iup_open.set_attribute(Current, "LINEY", value.out)
		end

	set_x_auto_hide (state: BOOLEAN)
		-- When enabled, if DX >= XMAX-XMIN then the horizontal scrollbar is 
		-- hidden. Default: "True".
		do
			iup_open.set_attribute(Current, "XAUTOHIDE", boolean_to_yesno(state))
		end

	set_y_auto_hide (state: BOOLEAN)
		-- When enabled, if DY >= YMAX-YMIN then the vertical scrollbar is 
		-- hidden. Default: "True".
		do
			iup_open.set_attribute(Current, "YAUTOHIDE", boolean_to_yesno(state))
		end

	--set_touch (state: BOOLEAN)
		-- [Windows 7 Only]: enable the multi-touch events processing.
	--	do
	--		iup_open.set_attribute(Current, "TOUCH", boolean_to_yesno(state))
	--	end

	set_wheel_drop_focus (state: BOOLEAN)
		-- If set to True when the wheel is used the focus control close any dropdown 
		-- opened. The default is False.
		do
			iup_open.set_attribute(Current, "WHEELDROPFOCUS", boolean_to_yesno(state))
		end

	-- Skip XDISPLAY, XWINDOW.

	-- For the MDI Client

	set_mdi_client (state: BOOLEAN)
		-- (creation only) [Windows Only] (non inheritable): Configure the canvas 
		-- as a MDI client. No callbacks will be called. This canvas will be used 
		-- internally only by the MDI Frame and its MDI Children. The MDI frame 
		-- must have one and only one MDI client. Default: "False".
		do
			iup_open.set_attribute(Current, "MDICLIENT", boolean_to_yesno(state))
		end

	set_mdi_menu (menu: STRING)
		-- (creation only) [Windows Only]: Name of a IUP_MENU to be used as the 
		-- Window list of a MDI frame. The system will automatically add the 
		-- list of MDI child windows there.
		do
			iup_open.set_attribute(Current, "MDIMENU", menu)
		end

	-- Callbacks

	-- Common
	set_cb_map (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Called right after an element is mapped and its attributes updated.
		local
			operation: INTEGER
		do
			cb_map := act
			
			if cb_map /= Void then
				operation := 1
			else
				operation := 0
			end
						
			iup_open.set_callback (Current, "MAP_CB", "NONEEDED", operation)
		end

	set_cb_unmap (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Called right before an element is unmapped.
		local
			operation: INTEGER
		do
			cb_unmap := act

			if cb_unmap /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "UNMAP_CB", "NONEEDED", operation)
		end

	set_cb_destroy (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Called right before an element is destroyed.
		local
			operation: INTEGER
		do
			cb_destroy := act

			if cb_destroy /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DESTROY_CB", "NONEEDED", operation)
		end

	set_cb_get_focus (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Action generated when an element is given keyboard focus. 
		-- This callback is called after the KILLFOCUS_CB of the element 
		-- that loosed the focus. The {IUP}.get_focus function during the 
		-- callback returns the element that loosed the focus.
		local
			operation: INTEGER
		do
			cb_getfocus := act

			if cb_getfocus /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "GETFOCUS_CB", "NONEEDED", operation)
		end

	set_cb_kill_focus (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Action generated when an element loses keyboard focus. This 
		-- callback is called before the GETFOCUS_CB of the element that 
		-- gets the focus.
		local
			operation: INTEGER
		do
			cb_killfocus := act

			if cb_killfocus /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "KILLFOCUS_CB", "NONEEDED", operation)
		end

	set_cb_enter_window (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Action generated when the mouse enters the native element. 
		local
			operation: INTEGER
		do
			cb_enterwindow := act

			if cb_enterwindow /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ENTERWINDOW_CB", "NONEEDED", operation)
		end

	set_cb_leave_window (act: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING])
		-- Action generated when the mouse leaves the native element.
		local
			operation: INTEGER
		do
			cb_leavewindow := act

			if cb_leavewindow /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "LEAVEWINDOW_CB", "NONEEDED", operation)
		end

	set_cb_k_any (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER], STRING])
		-- Action generated when a keyboard event occurs.
		-- IUP_WIDGET the element that activated the event.
		-- INTEGER identifier of typed key. Please refer to the Keyboard 
		-- Codes table for a list of possible values.
		--
		-- Returns: If IUP_IGNORE is returned the key is ignored and not
		-- processed by the control and not propagated. If returns 
		-- IUP_CONTINUE, the key will be processed and the event will be
		-- propagated to the parent of the element receiving it, this is 
		-- the default behavior. If returns IUP_DEFAULT the key is processed 
		-- but it is not propagated. IUP_CLOSE will be processed. 
		local
			operation: INTEGER
		do
			cb_k_any := act

			if cb_k_any /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "K_ANY", "NONEEDED", operation)
		end

	set_cb_help (act: detachable PROCEDURE[TUPLE[IUP_CANVAS]])
		-- Action generated when the user press F1 at a control. In Motif 
		-- is also activated by the Help button in some workstations 
		-- keyboard.
		-- Returns: IUP_CLOSE will be processed.
		local
			operation: INTEGER
		do
			cb_help := act

			if cb_help /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "HELP_CB", "NONEEDED", operation)
		end

	-- Extra

	set_cb_canvas_action (act: detachable FUNCTION[TUPLE[IUP_CANVAS, REAL_32, REAL_32], STRING])
		-- Action generated when the canvas needs to be redrawn.
		local
			operation: INTEGER
		do
			cb_canvas_action := act

			if cb_canvas_action /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "ACTION", "Fnff", operation)
		end

	set_cb_button (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when any mouse button is pressed and when it is 
		-- released. Both calls occur before the ACTION callback when button 1 is 
		-- being used.
		--
		-- IUP_CANVAS: identifies the element that activated the event.
		-- button: identifies the activated mouse button:
		--
		-- 1 - left mouse button (button 1);
		-- 2 - middle mouse button (button 2);
		-- 3 - right mouse button (button 3).
		--
		-- pressed: indicates the state of the button:
		--
		-- 0 - mouse button was released;
		-- 1 - mouse button was pressed.
		-- 
		-- x, y: position in the canvas where the event has occurred, in pixels.
		--
		-- status: status of the mouse buttons and some keyboard keys at the 
		-- moment the event is generated. The following IUP features must be used 
		-- for verification:
		--
		-- is_shift(status)
		-- is_control(status)
		-- is_button_1(status)
		-- is_button_2(status)
		-- is_button_3(status)
		-- is_button_4(status)
		-- is_button_5(status)
		-- is_double(status)
		-- is_alt(status)
		-- is_sys(status)
		--
		-- Returns: IUP_CLOSE will be processed. On some controls if IUP_IGNORE 
		-- is returned the action is ignored (this is system dependent).	
		local
			operation: INTEGER
		do
			cb_button := act

			if cb_button /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "BUTTON_CB", "NONEEDED", operation)
		end

	set_cb_drop_files (act: detachable FUNCTION[TUPLE[IUP_CANVAS, STRING, INTEGER, INTEGER, INTEGER], STRING])
		-- [Windows and GTK Only]: Action generated when one or more files are 
		-- dropped in the element.
		-- If defined after the element is mapped then the attribute 
		-- DROPFILESTARGET must be set to YES. [Windows and GTK Only] 
		local
			operation: INTEGER
		do
			cb_dropfiles := act

			if cb_dropfiles /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "DROPFILES_CB", "NONEEDED", operation)
		end

	set_cb_focus (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER], STRING])
		-- Called when the canvas gets or looses the focus. It is called after 
		-- the common callbacks GETFOCUS_CB and KILL_FOCUS_CB.
		-- ih: identifier of the element that activated the event.
		-- focus: is non zero if the canvas is getting the focus, is zero if it 
		-- is loosing the focus.
		local
			operation: INTEGER
		do
			cb_focus := act

			if cb_focus /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "FOCUS_CB", "NONEEDED", operation)
		end

	set_cb_motion (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when the mouse moves.
		-- ih: identifier of the element that activated the event.
		-- x, y: position in the canvas where the event has occurred, in pixels.
		-- status: status of mouse buttons and certain keyboard keys at the 
		-- moment the event was generated. The same macros used for BUTTON_CB can 
		-- be used for this status.
		local
			operation: INTEGER
		do
			cb_motion := act

			if cb_motion /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "MOTION_CB", "NONEEDED", operation)
		end

	set_cb_key_press (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER], STRING])
		-- Action generated when a key is pressed or released. If the key is 
		-- pressed and held several calls will occur. It is called after the 
		-- callback K_ANY is processed.
		-- ih: identifier of the element that activated the event.
		-- c: identifier of typed key. Please refer to the Keyboard Codes table 
		-- for a list of possible values.
		-- press: 1 is the user pressed the key or 0 otherwise.
		--
		-- Returns: If IUP_IGNORE is returned the key is ignored by the system. 
		-- IUP_CLOSE will be processed.
		local
			operation: INTEGER
		do
			cb_keypress := act

			if cb_keypress /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "KEYPRESS_CB", "NONEEDED", operation)
		end

	set_cb_resize (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER], STRING])
		-- Action generated when the canvas or dialog size is changed.
		--
		-- ih: identifier of the element that activated the event.
		-- width: the width of the internal element size in pixels not 
		-- considering the decorations (client size)
		-- height: the height of the internal element size in pixels not 
		-- considering the decorations (client size)
		-- When XAUTOHIDE=Yes or YAUTOHIDE=Yes, if the canvas scrollbar is 
		-- hidden/shown after changing the DX or DY attributes from inside the 
		-- callback, the size of the drawing area will immediately change, so the 
		-- parameters with and height will be invalid. To update the parameters 
		-- consult the DRAWSIZE attribute. Also activate the drawing toolkit only 
		-- after updating the DX or DY attributes.
		local
			operation: INTEGER
		do
			cb_resize := act

			if cb_resize /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "RESIZE_CB", "NONEEDED", operation)
		end

	set_cb_scroll (act: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, REAL_32, REAL_32], STRING])
		-- Called when some manipulation is made to the scrollbar. The canvas is 
		-- automatically redrawn only if this callback is NOT defined.
		--
		-- (GTK 2.8) Also the POSX and POSY values will not be correctly updated 
		-- for older GTK versions.
		--
		-- In Ubuntu, when liboverlay-scrollbar is enabled (the new tiny 
		-- auto-hide scrollbar) only the IUP_SBPOSV and IUP_SBPOSH codes are used.
		--
		-- ih: identifier of the element that activated the event.
		-- op: indicates the operation performed on the scrollbar.
		-- 
		-- If the manipulation was made on the vertical scrollbar, it can have 
		-- the following values:
		-- 
		-- 0 - line up
		-- 1 - line down
		-- 2 - page up
		-- 3 - page down
		-- 4 - vertical positioning
		-- 5 - vertical drag 
		-- 
		-- If it was on the horizontal scrollbar, the following values are valid:
		-- 
		-- 6 - column left
		-- 7 - column right
		-- 8 - page left
		-- 9 - page right
		-- 10 - horizontal positioning
		-- 11 - horizontal drag
		-- 
		-- posx, posy: the same as the ACTION canvas callback (corresponding to 
		-- the values of attributes POSX and POSY).
		--
		-- Notes:
		-- 
		-- vertical drag (5) and horizontal drag (11) are not supported in GTK.
		local
			operation: INTEGER
		do
			cb_scroll := act

			if cb_scroll /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "SCROLL_CB", "NONEEDED", operation)
		end

	set_cb_wheel (act: detachable FUNCTION[TUPLE[IUP_CANVAS, REAL_32, INTEGER, INTEGER, STRING], STRING])
		-- Action generated when the mouse wheel is rotated. If this callback is 
		-- not defined the wheel will automatically scroll the canvas in the 
		-- vertical direction by some lines, the SCROLL_CB callback if defined 
		-- will be called with the IUP_SBDRAGV operation.
		--
		-- ih: identifier of the element that activated the event.
		-- delta: the amount the wheel was rotated in notches.
		-- x, y: position in the canvas where the event has occurred, in pixels.
		-- status: status of mouse buttons and certain keyboard keys at the 
		-- moment the event was generated. The same macros used for BUTTON_CB can 
		-- be used for this status.
		--
		-- In Motif and GTK delta is always 1 or -1. In Windows is some 
		-- situations delta can reach the value of two. In the future with more 
		-- precise wheels this increment can be changed.
		local
			operation: INTEGER
		do
			cb_wheel := act

			if cb_wheel /= Void then
				operation := 1
			else
				operation := 0
			end
			
			iup_open.set_callback (Current, "WHEEL_CB", "NONEEDED", operation)
		end

	-- Skip TOUCH_CB, MULTITOUCH_CB, WOM_CB
	
feature {IUP}

	-- Internal handle of callbacks.

	-- Common callbacks
	
	execute_map: STRING
		do
			if attached cb_map as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_unmap: STRING
		do
			if attached cb_unmap as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_destroy: STRING
		do
			if attached cb_destroy as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_getfocus: STRING
		do
			if attached cb_getfocus as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_killfocus: STRING
		do
			if attached cb_killfocus as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_enterwindow: STRING
		do
			if attached cb_enterwindow as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_leavewindow: STRING
		do
			if attached cb_leavewindow as int_cb then
				Result := int_cb.item([Current])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_k_any (c: INTEGER): STRING
		do
			if attached cb_k_any as int_cb then
				Result := int_cb.item([Current, c])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_help
		do
			if attached cb_help as int_cb then
				int_cb.call([Current])
			end
		end

	-- Extra

	execute_action_fnff (posx, posy: REAL_32): STRING
		do
			if attached cb_canvas_action as int_cb then
				Result := int_cb.item([Current, posx, posy])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_button (btn, pressed, x, y: INTEGER; status: STRING): STRING
		do
			if attached cb_button as int_cb then
				Result := int_cb.item([Current, btn, pressed, x, y, status])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_dropfiles (filename: STRING; num: INTEGER; x: INTEGER; y: INTEGER): STRING
		do
			if attached cb_dropfiles as int_cb then
				Result := int_cb.item([Current, filename, num, x, y])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_focus (focus: INTEGER): STRING
		do
			if attached cb_focus as int_cb then
				Result := int_cb.item([Current, focus])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_motion (x, y: INTEGER; status: STRING): STRING
		do
			if attached cb_motion as int_cb then
				Result := int_cb.item([Current, x, y, status])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_keypress (c, press: INTEGER): STRING
		do
			if attached cb_keypress as int_cb then
				Result := int_cb.item([Current, c, press])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_resize (width, height: INTEGER): STRING
		do
			if attached cb_resize as int_cb then
				Result := int_cb.item([Current, width, height])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_scroll (op: INTEGER; posx, posy: REAL_32): STRING
		do
			if attached cb_scroll as int_cb then
				Result := int_cb.item([Current, op, posx, posy])
			else
				Result := "IUP_DEFAULT"
			end
		end

	execute_wheel (delta: REAL_32; x, y: INTEGER; status: STRING): STRING
		do
			if attached cb_wheel as int_cb then
				Result := int_cb.item([Current, delta, x, y, status])
			else
				Result := "IUP_DEFAULT"
			end
		end

feature {CD_IUP}
		
	set_cd_canvas (cd: CD_IUP)
		do
			internal_canvas := cd
		end

	set_back_and_front_cd_canvas (back_cd: CD_IUP)
		local
			fcd: CD_IUP
			p: POINTER
		do
			internal_canvas := back_cd

			p := iup_open.get_attribute_ihandle(Current, "")
			create fcd.create_with_front_cd_canvas(p)
			front_canvas := fcd
		end

feature {NONE}

	-- For CD

	internal_canvas: CD_IUP
		attribute
			create Result.create_default
		end

	front_canvas: CD_IUP
		attribute
			create Result.create_default
		end
	
	-- For callbacks
	cb_map: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_unmap: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_destroy: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_getfocus: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_killfocus: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_enterwindow: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_leavewindow: detachable FUNCTION[TUPLE[IUP_CANVAS], STRING]
	cb_k_any: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER], STRING]
	cb_help: detachable PROCEDURE[TUPLE[IUP_CANVAS]]
	
	cb_canvas_action: detachable FUNCTION[TUPLE[IUP_CANVAS, REAL_32, REAL_32], STRING]
	cb_button: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER, INTEGER, INTEGER, STRING], STRING]
	cb_dropfiles: detachable FUNCTION[TUPLE[IUP_CANVAS, STRING, INTEGER, INTEGER, INTEGER], STRING]
	cb_focus: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER], STRING]
	cb_motion: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER, STRING], STRING]
	cb_keypress: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER], STRING]
	cb_resize: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, INTEGER], STRING]
	cb_scroll: detachable FUNCTION[TUPLE[IUP_CANVAS, INTEGER, REAL_32, REAL_32], STRING]
	cb_wheel: detachable FUNCTION[TUPLE[IUP_CANVAS, REAL_32, INTEGER, INTEGER, STRING], STRING]

	-- Internals

	int_create_canvas (action: POINTER): POINTER
		external
			"C inline use %"eiffel-iup.h%""
      alias
			"return IupCanvas ($action);"
      end
	
end

-- The MIT License (MIT)

-- Copyright (c) 2016, 2017, 2019, 2020, 2021 by German A. Arias

-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in 
-- all copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.

